package com.obsidian.free.slideshow;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.format.Time;
import android.util.Log;

public class ImageDatabase extends SQLiteOpenHelper {
   final static private String DB_NAME = "images.db";
   final static private int DB_VERSION = 1;
   
   final static private String TABLE_WIDGETS = "widgets";
   final static public String WIDGETS_ID = "id";
   final static public String WIDGETS_TYPE = "type";
   final static public String WIDGETS_PERIOD = "period";
   final static public String WIDGETS_TAGS = "tags";
   final static public String WIDGETS_USERS = "users";
   final static public String WIDGETS_ORDER = "random";
   final static public String WIDGETS_CURRENT = "currentImage";
   final static public String WIDGETS_LASTUPDATE = "lastUpdate";
   final static public String WIDGETS_UPDATES = "updates";
   
   final static private String TABLE_IMAGES = "images";
   final static private String IMAGES_ID = "id";
   final static private String IMAGES_WIDGETID = "wid";
   final static private String IMAGES_DATA = "data";
   final static private String IMAGES_WEIGHT = "weight";
   
   public ImageDatabase(Context context) {
      super(context, DB_NAME, null, DB_VERSION);
   }

   @Override
   public void onCreate(SQLiteDatabase db) {
      db.execSQL("CREATE TABLE " + TABLE_WIDGETS + "(" +
                  WIDGETS_ID + " INTEGER PRIMARY KEY, " +
                  WIDGETS_TYPE + " INTEGER, " +
                  WIDGETS_PERIOD + " INTEGER, " +
                  WIDGETS_TAGS + " TEXT, " +
                  WIDGETS_USERS + " TEXT, " +
                  WIDGETS_ORDER + " INTEGER, " +
                  WIDGETS_CURRENT + " INTEGER, " +
                  WIDGETS_LASTUPDATE + " INTEGER, " +
                  WIDGETS_UPDATES + " INTEGER);");
      db.execSQL("CREATE TABLE " + TABLE_IMAGES + "(" +
                  IMAGES_ID + " INTEGER PRIMARY KEY, " +
                  IMAGES_WIDGETID + " INTEGER, " +
                  IMAGES_WEIGHT + " INTEGER, " +
                  IMAGES_DATA + " BLOB);");
   }

   @Override
   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      if(oldVersion != DB_VERSION) {
         db.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGES);
         db.execSQL("DROP TABLE IF EXISTS " + TABLE_WIDGETS);
         onCreate(db);
      }
   }
   
   public boolean createWidget(int appWidgetId, int type, int period,
                              String tags, String users, int order) {
      deleteWidget(appWidgetId);
      SQLiteDatabase db = getWritableDatabase();
      ContentValues values = new ContentValues();
      values.put(WIDGETS_ID, appWidgetId);
      values.put(WIDGETS_TYPE, type);
      values.put(WIDGETS_PERIOD, period);
      values.put(WIDGETS_TAGS, tags);
      values.put(WIDGETS_USERS, users);
      values.put(WIDGETS_ORDER, order);
      
      values.put(WIDGETS_CURRENT, 1);
      values.put(WIDGETS_LASTUPDATE, 0);
      values.put(WIDGETS_UPDATES, 0);
      
      return db.insert(TABLE_WIDGETS, null, values) > -1;
   }
   
   public void updateWidget(int appWidgetId, int period, int order) {
      SQLiteDatabase db = getWritableDatabase();
      
      ContentValues values = new ContentValues();
      values.put(WIDGETS_ORDER, order);
      values.put(WIDGETS_PERIOD, period);
      
      db.update(TABLE_WIDGETS, values, WIDGETS_ID + " = " + appWidgetId, null);
   }
   
   public void invalidateWidget(int appWidgetId) {
      SQLiteDatabase db = getWritableDatabase();
      
      ContentValues values = new ContentValues();
      values.put(WIDGETS_LASTUPDATE, 0);
      
      db.update(TABLE_WIDGETS, values, WIDGETS_ID + " = " + appWidgetId, null);
   }
   
   public void deleteWidget(int appWidgetId) {
      SQLiteDatabase db = getWritableDatabase();
      db.delete(TABLE_WIDGETS, WIDGETS_ID + " = " + appWidgetId, null);
      db.delete(TABLE_IMAGES, IMAGES_WIDGETID + " = " + appWidgetId, null);
   }

   public boolean needsUpdate(int appWidgetId) {
      SQLiteDatabase db = getWritableDatabase();
      Bundle widget = getWidget(appWidgetId);
      
      Time now = new Time();
      now.setToNow();
      Time last = new Time();
      last.set(widget.getLong(WIDGETS_LASTUPDATE));
      last.minute += widget.getInt(WIDGETS_PERIOD);
      last.second -= 5;
      
      if(last.before(now)) {
         Cursor c = db.query(TABLE_IMAGES, new String[] {IMAGES_ID, IMAGES_WEIGHT},
               IMAGES_WIDGETID + " = " + appWidgetId,
               null, null, null, IMAGES_WEIGHT);
         int updates = widget.getInt(WIDGETS_UPDATES);
         int current = widget.getInt(WIDGETS_CURRENT);
         long lastupdate = widget.getLong(WIDGETS_LASTUPDATE);
         if(c.getCount() == 0) {
            c.close();
            return false;
         }
         if(c.moveToFirst() && c.getCount() > 1) {
            while(!c.moveToLast()){}
            if(c.getInt(c.getColumnIndex(IMAGES_ID)) == current) {
               updates = 1;
               if(c.moveToFirst())
                  current = c.getInt(c.getColumnIndex(IMAGES_ID));
            }else{
               updates++;
               if(widget.getInt(WIDGETS_ORDER) == 1) {
                  Random rand = new Random();
                  int oldCurrent = current;
                  do { 
                     current = rand.nextInt(c.getCount());
                  }while(current == oldCurrent);
                  current++;
               }else{
                  while(!c.moveToFirst()) {}
                  do {
                     if(c.getInt(c.getColumnIndex(IMAGES_ID)) == current) {
                        c.moveToNext();
                        break;
                     }
                  }while(c.moveToNext());
                  current = c.getInt(c.getColumnIndex(IMAGES_ID));
               }
            }
         }
         lastupdate = now.toMillis(false);
         ContentValues values = new ContentValues();
         values.put(WIDGETS_CURRENT, current);
         values.put(WIDGETS_LASTUPDATE, lastupdate);
         values.put(WIDGETS_UPDATES, updates);
         
         db.update(TABLE_WIDGETS, values, WIDGETS_ID + " = " + appWidgetId, null);
         c.close();
         return true;
      }
      return false;
   }
   
   public boolean needsFlickrUpdate(int appWidgetId) {
      SQLiteDatabase db = getReadableDatabase();
      Cursor c = db.query(TABLE_WIDGETS, new String[] {WIDGETS_UPDATES},
            WIDGETS_ID + " = " + appWidgetId, null, null, null, null);
      
      if(c.moveToFirst()) {
         int updates = c.getInt(c.getColumnIndex(WIDGETS_UPDATES));
         c = db.query(TABLE_IMAGES, new String[] {IMAGES_ID},
               null, null, null, null, null);
         if(updates >= c.getCount()) {
            return true;
         }
      }
      return false;
   }
   
   public void setWidgetCurrent(int appWidgetId, int current) {
      SQLiteDatabase db = getWritableDatabase();
      ContentValues values = new ContentValues();
      values.put(WIDGETS_CURRENT, current);
      db.update(TABLE_WIDGETS, values, WIDGETS_ID + " = " + appWidgetId, null);
   }
   
   public int setImage(int appWidgetId, int weight, Bitmap bitmap) {
      SQLiteDatabase db = getWritableDatabase();
      Cursor c;
      if(weight < 0) {
         c = db.query(TABLE_IMAGES,
               new String[] {IMAGES_WEIGHT}, IMAGES_WIDGETID + " = " + appWidgetId,
               null, null, null, IMAGES_WEIGHT);
         if(c.getCount() < 1) {
            weight = 0; 
         }else if(c.moveToLast()) {
            weight = c.getInt(c.getColumnIndex(IMAGES_WEIGHT))+1;
         }
      }
      
      try {
         int size = bitmap.getWidth() * bitmap.getHeight() * 4;
         ByteArrayOutputStream out = new ByteArrayOutputStream(size);
         bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
         out.flush();
         out.close();
         
         ContentValues values = new ContentValues();
         values.put(IMAGES_WIDGETID, appWidgetId);
         values.put(IMAGES_WEIGHT, weight);
         values.put(IMAGES_DATA, out.toByteArray());
         db.insert(TABLE_IMAGES, null, values);
      }catch(IOException e){
         Log.e("SlideShow", "Error in ImageDatabase.setImage()", e);
      }
      
      c = db.query(TABLE_IMAGES, new String[] {IMAGES_ID},
            IMAGES_WEIGHT + " = " + weight + " AND " + IMAGES_WIDGETID + " = " + appWidgetId,
            null, null, null, null);
      while(!c.moveToFirst()){}
      int ret = c.getInt(c.getColumnIndex(IMAGES_ID));
      c.close();
      return ret;
   }
   
   public Bitmap getImage(int appWidgetId, int imageId) {
      Bitmap bitmap = null;
      SQLiteDatabase db = getReadableDatabase();
      byte[] bitmapData = null;
      Cursor c = db.query(TABLE_IMAGES, new String[] {IMAGES_ID, IMAGES_DATA, IMAGES_WEIGHT},
            IMAGES_ID + " = " + imageId + " AND " + IMAGES_WIDGETID + " = " + appWidgetId,
            null, null, null, IMAGES_WEIGHT);
      
      if(c.moveToFirst()) {
         bitmapData = c.getBlob(c.getColumnIndex(IMAGES_DATA));
         bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length);
      }
      c.close();
      return bitmap;
   }
   
   public void deleteImage(int appWidgetId, int position) {
      SQLiteDatabase db = getWritableDatabase();
      Cursor c = db.query(TABLE_IMAGES, new String[] {IMAGES_ID},
            IMAGES_WIDGETID + " = " + appWidgetId, null, null, null, IMAGES_WEIGHT);
      
      if(c.moveToFirst()) {
         int i = 0;
         while(i < position) {
            if(!c.moveToNext()) break;
            i++;
         }
         int id = c.getInt(c.getColumnIndex(IMAGES_ID));
         db.delete(TABLE_IMAGES, IMAGES_ID + " = " + id, null);
      }
   }
   
   public void moveImage(int appWidgetId, int position, int direction) {
      if(position == 0 && direction < 0) return;
      SQLiteDatabase db = getWritableDatabase();
      Cursor c = db.query(TABLE_IMAGES, new String[] {IMAGES_ID, IMAGES_WEIGHT},
            IMAGES_WIDGETID + " = " + appWidgetId, null, null, null, IMAGES_WEIGHT);
      
      if(position >= (c.getCount()-1) && direction > 0) {
         c.close();
         return;
      }
      
      if(c.moveToFirst()) {
         int i = 0;
         while(i < position) {
            if(!c.moveToNext()) break;
            i++;
         }
         int id = c.getInt(0);
         int weight = c.getInt(1);
         int newID = -1, newWeight = -1;
         if(direction < 0) {
            if(c.moveToPrevious()) {
               newID = c.getInt(0);
               newWeight = c.getInt(1);
            }
         }else if(direction > 0) {
            if(c.moveToNext()) {
               newID = c.getInt(0);
               newWeight = c.getInt(1);
            }
         }else{
            c.close();
            return;
         }
         
         ContentValues values = new ContentValues();
         values.put(IMAGES_WEIGHT, newWeight);
         db.update(TABLE_IMAGES, values, IMAGES_ID + " = " + id, null);
         
         values = new ContentValues();
         values.put(IMAGES_WEIGHT, weight);
         db.update(TABLE_IMAGES, values, IMAGES_ID + " = " + newID, null);
         c.close();
      }
   }
   
   public Bundle getWidget(int appWidgetId) {
      SQLiteDatabase db = getReadableDatabase();
      Cursor c = db.query(TABLE_WIDGETS,
            new String[] {WIDGETS_CURRENT, WIDGETS_LASTUPDATE, WIDGETS_ORDER,
                           WIDGETS_PERIOD, WIDGETS_TAGS, WIDGETS_USERS, WIDGETS_TYPE,
                           WIDGETS_UPDATES},
            WIDGETS_ID + " = " + appWidgetId, null, null, null, null);
      
      Bundle bundle = new Bundle();
      if(c.moveToFirst()) {
         bundle.putInt(WIDGETS_CURRENT,     new Integer(c.getInt(c.getColumnIndex(WIDGETS_CURRENT))));
         bundle.putLong(WIDGETS_LASTUPDATE, new Long(c.getLong(c.getColumnIndex(WIDGETS_LASTUPDATE))));
         bundle.putInt(WIDGETS_ORDER,       new Integer(c.getInt(c.getColumnIndex(WIDGETS_ORDER))));
         bundle.putInt(WIDGETS_PERIOD,      new Integer(c.getInt(c.getColumnIndex(WIDGETS_PERIOD))));
         bundle.putString(WIDGETS_TAGS,     c.getString(c.getColumnIndex(WIDGETS_TAGS)));
         bundle.putString(WIDGETS_USERS,    c.getString(c.getColumnIndex(WIDGETS_USERS)));
         bundle.putInt(WIDGETS_TYPE,        new Integer(c.getInt(c.getColumnIndex(WIDGETS_TYPE))));
         bundle.putInt(WIDGETS_UPDATES,     new Integer(c.getInt(c.getColumnIndex(WIDGETS_UPDATES))));
      }
      c.close();
      return bundle;
   }
   
   public Bundle getWidgetImages(int appWidgetId) {
       SQLiteDatabase db = getReadableDatabase();
       Cursor c = db.query(TABLE_IMAGES,
               new String[] {IMAGES_DATA},
               IMAGES_WIDGETID + " = " + appWidgetId,
               null, null, null, IMAGES_WEIGHT);
       
       Bitmap[] bmps = new Bitmap[c.getCount()];
       Bundle ret = new Bundle();
       
       int i = 0;
       if(c.moveToFirst()) {
           do {
               byte[] data = c.getBlob(c.getColumnIndex(IMAGES_DATA));
               Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
               bmps[i] = bitmap;
               i++;
           }while(c.moveToNext());
       }
       
       ret.putParcelableArray("images", bmps);
       c.close();
       return ret;
   }
}
